﻿using mozhi.smarterp.Finance.Enums;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Volo.Abp;

namespace mozhi.smarterp.Finance.Finances
{
    /// <summary>
    /// 期末处理
    /// </summary>
    public class EndPeriodProcessResult : AggregateRootBase<Guid>
    {
        /// <summary>
        /// 期末处理项
        /// </summary>
        public Guid ItemId { private set; get; }

        /// <summary>
        /// 期间
        /// </summary>
        public int Period { private set; get; }

        /// <summary>
        /// 凭证号
        /// </summary>
        public Guid? JournalId { private set; get; }

        /// <summary>
        /// 是否需要处理
        /// </summary>
        public bool NeedProcess { private set; get; }

        public bool NeedEdit { private set; get; }

        /// <summary>
        /// 是否完成
        /// </summary>
        public bool Finshed { private set; get; }

        public EndPeriodProcessType Type { private set; get; }

        public decimal? MeasureValue { private set; get; }

        public List<EndPeriodProcessResultItem> Items { private set; get; }

        private EndPeriodProcessResult() { }

        public EndPeriodProcessResult(Guid id, Guid itemId, int period, EndPeriodProcessType type)
        {
            Id = id;
            ItemId = itemId;
            Period = period;
            Items = new List<EndPeriodProcessResultItem>();
            Type = type;

            Validate();
        }

        public void Change(bool needProcess, bool finished, Guid? journalId, decimal? measureValue , bool needEdit)
        {
            NeedProcess = needProcess;
            MeasureValue = measureValue;
            Finshed = finished;
            JournalId = journalId;
            NeedEdit = needEdit;
        }

        public void AddItem(EndPeriodProcessResultItem item)
        {
            if (Items.Exists(x => x.Index == item.Index))
                throw new BusinessException("100000", $"期末处理结果已经包含了序号为{item.Index}的项");

            var match = Items.FirstOrDefault(x => x.Id == item.Id);

            if (match == null)
                Items.Add(item);
            else
                match.Change(item.Value, item.ValueType);
        }


        private void Validate()
        {
            if (ItemId == default)
                throw new ArgumentNullException(nameof(ItemId));
            if (Period <= 0)
                throw new ArgumentNullException(nameof(Period));

            if (Type == default)
                throw new ArgumentNullException(nameof(Type));
        }

    }

    /// <summary>
    /// 期末处理结果项
    /// </summary>
    public class EndPeriodProcessResultItem : EntityBase<Guid>
    {
        public Guid EndPeriodProcessResultId { set; get; }
        public string Name { private set; get; }

        public string Value { private set; get; }

        /// <summary>
        /// 1金额 2百分比，3文本，4 guid
        /// </summary>
        public int ValueType { private set; get; }

        public int Index { private set; get; }

        public bool NeedEdit { private set; get; }

        private EndPeriodProcessResultItem() { }

        public EndPeriodProcessResultItem(Guid id, Guid resultId, string name, string value, int valueType, int index, bool needEdit)
        {
            Id = id;
            EndPeriodProcessResultId = resultId;
            Name = name;
            Value = value;
            ValueType = valueType;
            Index = index;
            NeedEdit = needEdit;

            Validate();
           
        }

        public void Change(string value, int valueType)
        {
            Value = value;
            ValueType = valueType;

            Validate();
        }

        private void Validate()
        {
            if (EndPeriodProcessResultId == default)
                throw new ArgumentNullException();

            if (Name.IsNullOrEmpty())
                throw new ArgumentNullException(nameof(Name));

            if (ValueType <= 0 && ValueType >= 4)
                throw new ArgumentOutOfRangeException(nameof(ValueType));

            if (Index == 0)
                throw new ArgumentOutOfRangeException(nameof(Index));
        }
    }
}
